#include "ET++.ph"
#ifdef __GNUG__
#pragma implementation
#endif

#include "ScrollBar.h"

#include "Class.h"
#include "Slider.h"
#include "Buttons.h"
#include "Look.h"

//---- ScrollBarButton ---------------------------------------------------------

class ScrollBarButton: public Button {
	int dir;
public:
	ScrollBarButton(int id, int d) : Button(id)
		{ dir= d; SetFlag(eVObjHFixed | eVObjVFixed); SetFlag(eButtonIdle); }
	void DrawInner(Rectangle r, bool highlight);
	Metric GetMinSize()
		{ return gLook->ScrollButtonLayout()->GetMinSize(this); }
};

void ScrollBarButton::DrawInner(Rectangle r, bool highlight)
{
	int code= dir;
	if (Enabled())
		SETBIT(code, 3);
	if (highlight)
		SETBIT(code, 4);
	gLook->ScrollButtonLayout()->Adorn(this, r, code);
	Button::Draw(r);
}

//---- ScrollBarThumb ----------------------------------------------------------

class ScrollBarThumb: public Thumb {
public:
	ScrollBarThumb(Slider *sl, Direction d) : Thumb(sl, d)
		{ }
	void Draw(Rectangle)
		{ gLook->ThumbLayout()->Adorn(this, contentRect); }
	Metric GetMinSize()
		{ return gLook->ThumbLayout()->GetMinSize(this); }
};

//---- ScrollBarSlider ---------------------------------------------------------

class ScrollBarSlider: public Slider {
public:
	ScrollBarSlider(int id= cIdNone, Direction d= eVert) : Slider(id, d)
		{ }
	Thumb *MakeThumb()
		{ return new ScrollBarThumb(this, dir); }
	void Draw(Rectangle);
	Metric GetMinSize()
		{ return thumb->GetMinSize(); }
};

void ScrollBarSlider::Draw(Rectangle r)
{
	gLook->SliderLayout()->Adorn(this, contentRect);
	CompositeVObject::Draw(r);
}

//---- ScrollBar ---------------------------------------------------------------

NewMetaImpl(ScrollBar,Expander, (TP(slider), TE(dir)));

ScrollBar::ScrollBar(int id, Direction d) : Expander(id, d, gPoint0)
{
	slider= 0;
	dir= d;
}

VObject *ScrollBar::MakePart(int id)
{
	switch (id) {
	case eScrollBarUpLeft:
		return new ScrollBarButton(id, dir ? 0 : 2);
	case eScrollBarSlider:
		return new ScrollBarSlider(id, dir);
	case eScrollBarDownRight:
		return new ScrollBarButton(id, dir ? 1 : 3);
	}
	return 0;
}

void ScrollBar::MakeParts()
{
	Add(MakePart(eScrollBarUpLeft));
	Add(slider= (Slider*) MakePart(eScrollBarSlider));
	Add(MakePart(eScrollBarDownRight));
}

void ScrollBar::SetContainer(VObject *v)
{
	if (slider == 0)
		MakeParts();
	Expander::SetContainer(v);
}

void ScrollBar::Draw(Rectangle)
{
	gLook->ScrollBarLayout()->Adorn(this, contentRect);
}

void ScrollBar::SetMax(const Point &vsz)
{
	slider->SetMax(vsz, TRUE);
}

void ScrollBar::SetVal(const Point &relOrig)
{
	slider->SetVal(relOrig, TRUE);
}

void ScrollBar::SetThumbRange(const Point &sz)
{
	slider->SetThumbRange(sz, TRUE);
}

void ScrollBar::SetAll(const Point &e, const Point &rng, const Point &mx)
{
	SetExtent(e);
	slider->SetThumbRange(rng);
	slider->SetMax(mx, TRUE);
}

void ScrollBar::Control(int id, int part, void *val)
{
	Point scroll;

	switch (id) {
	case eScrollBarUpLeft:
		part= cPartScrollStep;
		scroll[dir]= -1;
		break;
	case eScrollBarDownRight:
		part= cPartScrollStep;
		scroll[dir]= 1;
		break;
	case eScrollBarSlider:
		switch (part) {
		case eSliderPageUpLeft:
			part= cPartScrollPage;
			scroll[dir]= -1;
			break;
		case eSliderPageDownRight:
			part= cPartScrollPage;
			scroll[dir]= 1;
			break;
		case eSliderThumb:
			if (dir) {
				part= cPartScrollVAbs;
				scroll.y= ((Point*)val)->y;
			} else {
				part= cPartScrollHAbs;
				scroll.x= ((Point*)val)->x;
			}
			break;
		}
		break;
	default:
		VObject::Control(id, part, val);
		return;
	}
	VObject::Control(GetId(), part, &scroll);
}

